package com.yulan.bankback.xxlJob;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yulan.bankback.entity.constant.RedisKeyConstant;
import com.yulan.bankback.entity.event.AttackEvent;
import com.yulan.bankback.entity.model.admin.*;
import com.yulan.bankback.entity.model.bank.BankUser;
import com.yulan.bankback.entity.model.bank.UserCapitalFlow;
import com.yulan.bankback.log.Logger;
import com.yulan.bankback.mapper.admin.*;
import com.yulan.bankback.mapper.admin.webAttack.AttackEventMapper;
import com.yulan.bankback.mapper.bank.BankUserMapper;
import com.yulan.bankback.mapper.bank.UserCapitalFlowMapper;
import com.yulan.bankback.service.bank.BankService;
import com.yulan.bankback.service.bank.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
public class BuildDataJobHandler implements InitializingBean {

    private static String[] citys = {
            "市辖区", "石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市",
            "太原市", "大同市", "阳泉市", "长治市", "晋城市", "朔州市", "晋中市", "运城市", "忻州市", "临汾市", "吕梁市", "呼和浩特市",
            "包头市", "乌海市", "赤峰市", "通辽市", "鄂尔多斯市", "呼伦贝尔市", "巴彦淖尔市", "乌兰察布市", "兴安盟", "锡林郭勒盟", "阿拉善盟",
            "沈阳市", "大连市", "鞍山市", "抚顺市", "本溪市", "丹东市", "锦州市", "营口市", "阜新市", "辽阳市", "盘锦市", "铁岭市", "朝阳市",
            "葫芦岛市", "长春市", "吉林市", "四平市", "辽源市", "通化市", "白山市", "松原市", "白城市", "延边朝鲜族自治州", "哈尔滨市", "齐齐哈尔市",
            "鸡西市", "鹤岗市", "双鸭山市", "大庆市", "伊春市", "佳木斯市", "七台河市", "牡丹江市", "黑河市", "绥化市", "大兴安岭地区", "南京市",
            "无锡市", "徐州市", "常州市", "苏州市", "南通市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市", "杭州市",
            "宁波市", "温州市", "嘉兴市", "湖州市", "绍兴市", "金华市", "衢州市", "舟山市", "台州市", "丽水市", "合肥市", "芜湖市", "蚌埠市",
            "淮南市", "马鞍山市", "淮北市", "铜陵市", "安庆市", "黄山市", "滁州市", "阜阳市", "宿州市", "六安市", "亳州市", "池州市", "宣城市",
            "福州市", "厦门市", "莆田市", "三明市", "泉州市", "漳州市", "南平市", "龙岩市", "宁德市", "南昌市", "景德镇市", "萍乡市", "九江市",
            "新余市", "鹰潭市", "赣州市", "吉安市", "宜春市", "抚州市", "上饶市", "济南市", "青岛市", "淄博市", "枣庄市", "东营市", "烟台市",
            "潍坊市", "济宁市", "泰安市", "威海市", "日照市", "临沂市", "德州市", "聊城市", "滨州市", "菏泽市", "郑州市", "开封市", "洛阳市",
            "平顶山市", "安阳市", "鹤壁市", "新乡市", "焦作市", "濮阳市", "许昌市", "漯河市", "三门峡市", "南阳市", "商丘市", "信阳市", "周口市",
            "驻马店市", "省直辖县级行政区划", "武汉市", "黄石市", "十堰市", "宜昌市", "襄阳市", "鄂州市", "荆门市", "孝感市", "荆州市", "黄冈市",
            "咸宁市", "随州市", "恩施土家族苗族自治州", "长沙市", "株洲市", "湘潭市", "衡阳市", "邵阳市", "岳阳市", "常德市", "张家界市", "益阳市",
            "郴州市", "永州市", "怀化市", "娄底市", "湘西土家族苗族自治州", "广州市", "韶关市", "深圳市", "珠海市", "汕头市", "佛山市", "江门市",
            "湛江市", "茂名市", "肇庆市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市", "东莞市", "中山市", "潮州市", "揭阳市", "云浮市",
            "南宁市", "柳州市", "桂林市", "梧州市", "北海市", "防城港市", "钦州市", "贵港市", "玉林市", "百色市", "贺州市", "河池市", "来宾市", "崇左市",
            "海口市", "三亚市", "三沙市", "儋州市", "县", "成都市", "自贡市", "攀枝花市", "泸州市", "德阳市", "绵阳市", "广元市", "遂宁市", "内江市",
            "乐山市", "南充市", "眉山市", "宜宾市", "广安市", "达州市", "雅安市", "巴中市", "资阳市", "阿坝藏族羌族自治州", "甘孜藏族自治州", "凉山彝族自治州",
            "贵阳市", "六盘水市", "遵义市", "安顺市", "毕节市", "铜仁市", "黔西南布依族苗族自治州", "黔东南苗族侗族自治州", "黔南布依族苗族自治州",
            "昆明市", "曲靖市", "玉溪市", "保山市", "昭通市", "丽江市", "普洱市", "临沧市", "楚雄彝族自治州", "红河哈尼族彝族自治州", "文山壮族苗族自治州",
            "西双版纳傣族自治州", "大理白族自治州", "德宏傣族景颇族自治州", "怒江傈僳族自治州", "迪庆藏族自治州", "拉萨市", "日喀则市", "昌都市", "林芝市",
            "山南市", "那曲市", "阿里地区", "西安市", "铜川市", "宝鸡市", "咸阳市", "渭南市", "延安市", "汉中市", "榆林市", "安康市", "商洛市", "兰州市",
            "嘉峪关市", "金昌市", "白银市", "天水市", "武威市", "张掖市", "平凉市", "酒泉市", "庆阳市", "定西市", "陇南市", "临夏回族自治州", "甘南藏族自治州",
            "西宁市", "海东市", "海北藏族自治州", "黄南藏族自治州", "海南藏族自治州", "果洛藏族自治州", "玉树藏族自治州", "海西蒙古族藏族自治州", "银川市",
            "石嘴山市", "吴忠市", "固原市", "中卫市", "乌鲁木齐市", "克拉玛依市", "吐鲁番市", "哈密市", "昌吉回族自治州", "博尔塔拉蒙古自治州", "巴音郭楞蒙古自治州",
            "阿克苏地区", "克孜勒苏柯尔克孜自治州", "喀什地区", "和田地区", "伊犁哈萨克自治州", "塔城地区", "阿勒泰地区", "自治区直辖县级行政区划"
    };

    private static String[] attackTypes = {
            "xss跨站脚本攻击","CSRF跨站攻击","SQL注入攻击","Script/ActiveX攻击"
    };

    private static String[] violationTypes = {
            "多次异地登陆","与违规用户发生交易","对系统进行网络攻击"
    };


    private static String[] abnormalTypes = {
            "异地修改密码", "异地修改手机号","异地修改支付密码",
            "异地绑定银行卡","异地提现", "异地转账"
    };


    @Autowired
    private BankService bankService;

    @Autowired
    private RedisService redisService;

    @Resource
    private BankUserMapper bankUserMapper;

    @Resource
    private UserCapitalFlowMapper userCapitalFlowMapper;

    @Resource
    private AbnormalUserMapper abnormalUserMapper;

    @Resource
    private IllegalTradingMapper illegalTradingMapper;

    @Resource
    private ViolationUserMapper violationUserMapper;

    @Resource
    private RemoteLoginEventMapper remoteLoginEventMapper;

    @Resource
    private AttackEventMapper attackEventMapper;

    @Resource
    private KindUserMapper kindUserMapper;

    @Autowired
    private Logger logger;


    private AtomicInteger inc = new AtomicInteger(0);

    private AtomicInteger randomInc = new AtomicInteger(1);

    private List<BankUser> executeBankUsers = new ArrayList<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        executeBankUsers = getHundredUser();
        log.info(">>>>>>>>>> 已初始化随机用户列表 >>>>>>>>>>");
    }


    private List<BankUser> getHundredUser(){
        int limit = 100;
        int page = inc.getAndIncrement() % 20 * limit;
        List<BankUser> bankUsers = bankUserMapper.selectList(
                new QueryWrapper<BankUser>()
                        .last("limit " + page + ", " + limit));
        bankUsers.forEach(item -> redisService.lpush("user_id_list", item.getId()));
        return bankUsers;
    }

    private String getRandomIp(){
        StringBuilder ip = new StringBuilder();
        Random ipRandom = new Random(randomInc.getAndIncrement());
        ip.append(ipRandom.nextInt(255)).append(".")
            .append(ipRandom.nextInt(255)).append(".")
                .append(ipRandom.nextInt(255)).append(".")
                .append(ipRandom.nextInt(255));
        return ip.toString();
    }

    private BankUser getRandomUser(){
        Random userRandom = new Random(randomInc.getAndIncrement());
        BankUser user = executeBankUsers.get(userRandom.nextInt(100));
        return user;
    }

    private String getRandomCity(){
        Random cityRandom = new Random(randomInc.getAndIncrement());
        String city = citys[cityRandom.nextInt(citys.length)];
        return city;
    }

    /**
     * 刷新用户列表
     */
    @XxlJob("flushUserListJobHandler")
    public ReturnT<String> updateUserList(String s) throws Exception {
        log.info("开始更新用户名单");
        executeBankUsers = getHundredUser();
        log.info("已完成更新用户名单");
        return ReturnT.SUCCESS;
    }

    /**
     * 生成用户转账
     */
    @XxlJob("buildUserCapitalFlowJobHandler")
    public ReturnT<String> executeBuildMoneyFlow(String s) throws Exception {
        log.info("开始生成用户转账记录");
        Random srcUserRandom = new Random(randomInc.getAndIncrement());
        Random destUserRandom = new Random(randomInc.getAndIncrement());
        Random randomMoney = new Random(randomInc.getAndIncrement());
        int srcIndex = srcUserRandom.nextInt(100);
        int destIndex = destUserRandom.nextInt(100);
        while (destIndex == srcIndex){
            destIndex = destUserRandom.nextInt(100);
        }

        BankUser srcUser = executeBankUsers.get(srcIndex);
        BankUser destUser = executeBankUsers.get(destIndex);

        double money = (double) randomMoney.nextInt(100000);

        userCapitalFlowMapper.insert(new UserCapitalFlow(srcUser.getId(),money,
                "expend", new Date(), "", new Date(), "转账给其他用户("+ destUser.getPhone() + ")", 0));


        userCapitalFlowMapper.insert(new UserCapitalFlow(destUser.getId(), money,
                "income", new Date(), "", new Date(), "接收其他用户(" + srcUser.getPhone() + ")的转账", 0));

        //如果是违规用户
        if(violationUserMapper.selectById(destUser.getId()) != null){
            illegalTradingMapper.insert(new IllegalTrading(UUID.randomUUID().toString().replaceAll("-",""),
                    srcUser.getId(), srcUser.getUserName(), new Date(),"", "与违规用户发生交易",money, 0));
        }

        logger.logMoneyFlow(srcUser.getId(),destUser.getId(), String.valueOf(money),"transfer");

        log.info("已完成生成用户转账记录");
        return ReturnT.SUCCESS;
    }


    /**
     * 生成用户常异地登陆
     */
    @XxlJob("buildUserRemoteLoginJobHandler")
    public ReturnT<String> executeBuildRemoteLogin(String s) throws Exception {
        log.info("开始生成用户异地登陆");
        Random userRandom = new Random(randomInc.getAndIncrement());
        Random placeRandom = new Random(randomInc.getAndIncrement());
        BankUser user = executeBankUsers.get(userRandom.nextInt(100));
        String place = citys[placeRandom.nextInt(citys.length)];
        String ip = getRandomIp();
        remoteLoginEventMapper.insert(new RemoteLoginEvent(user.getId(), ip,
                place, new Date(), ""));
        logger.logRemoteLogin(user.getId(), ip, place);
        log.info("已完成生成用户异地登陆");
        return ReturnT.SUCCESS;
    }

    /**
     * 生成用户使用时间
     */
    @XxlJob("buildUserUseTimeJobHandler")
    public ReturnT<String> executeUserUseTime(String s) throws Exception {
        log.info("开始生成用户使用时长");
        Random userRandom = new Random(randomInc.getAndIncrement());
        Random useTimeRandom = new Random(randomInc.getAndIncrement());
        BankUser user = executeBankUsers.get(userRandom.nextInt(100));
        Long useTime = useTimeRandom.nextLong() % 1000000;
        redisService.hSet("use_time_map", user.getId(), String.valueOf(useTime), RedisKeyConstant.ONE_DAY, TimeUnit.MILLISECONDS);
        log.info("已完成生成用户使用时长");
        return ReturnT.SUCCESS;
    }


    /**
     * 生成攻击事件
     */
    @XxlJob("buildAttackEventJobHandler")
    public ReturnT<String> executeAttackEvent(String s) throws Exception {
        log.info("开始生成攻击事件");
        Random attackRandom = new Random(randomInc.getAndIncrement());
        String type = attackTypes[attackRandom.nextInt(attackTypes.length)];
        String ip = getRandomIp();
        AttackEvent attackEvent = new AttackEvent();
        attackEvent.setIsBlack(0);
        attackEvent.setAttackLevel(3);
        attackEvent.setCreateTime(new Date());
        attackEvent.setIp(ip);
        attackEvent.setType(type);
        attackEventMapper.insert(attackEvent);
        logger.logAttack(ip, "", type, String.valueOf(new Random().nextInt(2) + 1));
        log.info("已完成生成攻击事件");
        return ReturnT.SUCCESS;
    }

    /**
     * 生成攻击事件
     */
    @XxlJob("buildViolationUserJobHandler")
    public ReturnT<String> executeViolationUserEvent(String s) throws Exception {
        log.info("开始生成违规用户");
        Random random = new Random(randomInc.getAndIncrement());
        BankUser user = getRandomUser();
        ViolationUser violationUser = new ViolationUser();
        violationUser.setCity(getRandomCity());
        violationUser.setUsername(user.getUserName());
        violationUser.setViolationTime(new Date());
        violationUser.setViolationType(violationTypes[random.nextInt(3)]);
        violationUser.setUid(user.getId());
        violationUser.setBornDate(user.getBornDate());
        violationUserMapper.insert(violationUser);
        log.info("已完成生成违规用户");
        return ReturnT.SUCCESS;
    }

    /**
     * 生成黑名单
     */
    @XxlJob("buildBlackUserJobHandler")
    public ReturnT<String> executeBlackUserEvent(String s) throws Exception {
        log.info("开始生成黑名单用户");
        Random random = new Random(randomInc.getAndIncrement());
        BankUser user = getRandomUser();
        KindUser blackUser = new KindUser();
        blackUser.setType(violationTypes[random.nextInt(3)]);
        blackUser.setUid(user.getId());
        blackUser.setUsername(user.getUserName());
        blackUser.setBlackOrWhite("black");
        blackUser.setCreateTime(new Date());
        kindUserMapper.insert(blackUser);
        log.info("已完成生成黑名单用户");
        return ReturnT.SUCCESS;
    }


    /**
     * 生成异常账号
     */
    @XxlJob("buildAbnormalUserJobHandler")
    public ReturnT<String> executeAbnormalUserEvent(String s) throws Exception {
        log.info("开始生成异常用户");
        Random random = new Random(randomInc.getAndIncrement());
        BankUser user = getRandomUser();
        AbnormalUser abnormalUser = new AbnormalUser();
        abnormalUser.setUsername(user.getUserName());
        abnormalUser.setIp(getRandomIp());
        abnormalUser.setType(abnormalTypes[random.nextInt(6)]);
        abnormalUser.setCreateTime(new Date());
        abnormalUser.setUid(user.getId());
        abnormalUserMapper.insert(abnormalUser);
        log.info("已完成生成异常用户");
        return ReturnT.SUCCESS;
    }

    /**
     * 生产异常日志
     */
    @XxlJob("buildAbnormalJobHandler")
    public ReturnT<String> executeAbnormalEvent(String s) throws Exception {
        log.info("开始生成异常日志");
        BankUser user = getRandomUser();
        Random abnormalRandom = new Random(randomInc.getAndIncrement());
        logger.logAbnormal(user.getId(), abnormalTypes[abnormalRandom.nextInt(abnormalTypes.length)]);
        log.info("已完成生成异常日志");
        return ReturnT.SUCCESS;
    }

    /**
     * 生产充值日志
     */
    @XxlJob("buildRechargeJobHandler")
    public ReturnT<String> executeBuildRechage(String s) throws Exception {
        log.info("开始生成充值日志");
        BankUser user = getRandomUser();
        Random moneyRandom = new Random(inc.getAndIncrement());
        double money = (double) moneyRandom.nextInt(100000);
        logger.logRecharge(user.getId(), String.valueOf(money));
        log.info("已完成生成充值日志");
        return ReturnT.SUCCESS;
    }







}
